// 20210107 canvas01 script
import DiskCanvas from "../classes/DiskCanvas.js";
import {Point, Triangle, TextLabel} from "../classes/Shape.js";
import {MyDetail} from "../classes/MyUI.js";

// The info details.
const detail = new MyDetail(
    "磁盘调度策略",
    [
        "By Louis，2021-01-11；",
        "默认磁道的范围是 [0, 99] ，指定参数需要在这个区间内；",
        "需要指定磁盘起始的磁道和一个调度序列，序列部分至少输入一个数字；",
        "提供了先来先服务算法、最短寻找时间优先算法、SCAN 算法、循环扫描 C-SCAN 算法；"
    ],
);
document.getElementById("detail").appendChild(detail.getElement());

// The test data.
let list_nodes = [1, 30, 40, 10, 25, 99, 50, 60];
let show_list = [];
// Set a Timer
let time_interval = null;
// init the showList
const initShowList = (initLocation) => {
    show_list.push(new Point(initLocation, 0));
};


// add the disk canvas to the page.
let diskCanvas = new DiskCanvas(800, 600, {
    border: "1px solid gray",
});
diskCanvas.set_base(20, 30);
diskCanvas.set_delta_x(6);
diskCanvas.set_delta_y(2);
document.getElementById("canvas_here").appendChild(diskCanvas.getElement());

// The triangle pointing to the magnetic head.
let pointer = new Triangle(new Point(0, 0), new Point(-1, -10), new Point(1, -10));

// A text showing the track number.
let trackNumberText = new TextLabel({
    x: 1,
    y: -2,
    text: "Pointer",
    font: "20px Arial"
});

// Start the Timer.
const begin_interval = () => {
    console.log("Animation begin.");
    time_interval = setInterval(() => {
        // clear
        diskCanvas.clear_all();
        const get_next = () => {
            // Here we should decide the next based on the concrete algorithm.
            // The default algorithm is 'FCFS'.
            let x = list_nodes.shift();
            show_list[0].mark = true;
            let new_point = new Point(x, 0);
            new_point.mark = false;
            show_list.unshift(new_point);
        };
        // move
        for (let i = 0; i < show_list.length; i++) {
            show_list[i].moveY(1);
        }
        if (show_list.length > 0) {
            show_list[0].y = 0;
        } else {
            console.log("show_list.length===0")
        }
        // move 2
        let action = list_nodes[0] > show_list[0].x ? 1 : -1;
        show_list[0].moveX(action);
        pointer.moveX(action);
        trackNumberText.moveX(action);
        // draw
        diskCanvas.draw_a_line(new Point(0, 0), new Point(100, 0));
        diskCanvas.draw_triangle(pointer);
        // control
        if (list_nodes.length === 0) {
            stop_interval();
        }
        if (show_list[0].x === list_nodes[0]) {
            get_next();
        }
        // set
        trackNumberText.text = String(show_list[0].x);
        // draw
        diskCanvas.draw_text(trackNumberText);
        diskCanvas.draw_joint_lines(show_list);
        diskCanvas.draw_point_with_circle(show_list, 5);
    }, 20);
};

// To stop the timer.
const stop_interval = () => {
    window.clearInterval(time_interval);
    time_interval = null;
    console.log("Animation end.");
};

// generate the list_node depend on the algorithm.
const generate_list_node = (how, location) => {
    if (how === "SSTF") {
        list_nodes.unshift(location);
        for (let i = 1;i<list_nodes.length - 1;i++){
            for (let j = i + 1;j<list_nodes.length;j++){
                let originalDistance = Math.abs(list_nodes[i] - list_nodes[i-1]);
                if (Math.abs(list_nodes[j]-list_nodes[i-1]) < originalDistance){
                     let temp = list_nodes[i];
                     list_nodes[i] = list_nodes[j];
                     list_nodes[j] = temp;
                 }
            }
        }
        console.log("SSTF", list_nodes);
        list_nodes.shift();
        return;
    }
    // default go up first on the options above
    if (how === "SCAN") {
        if (list_nodes.indexOf(99) < 0) list_nodes.push(99);
        if (list_nodes.indexOf(0) < 0) list_nodes.push(0);
        console.log(list_nodes);
        list_nodes.unshift(location);
        console.log("SCAN:before sort", list_nodes);
        // sort()
        list_nodes.sort((a, b)=>{return a - b});
        console.log("SCAN:sort", list_nodes);
        let temp_location = list_nodes.indexOf(location);
        let temp = [];
        for (let i = temp_location;i<list_nodes.length;i++){
            temp.push(list_nodes[i]);
        }
        for (let i = temp_location-1;i>=0;i--){
            temp.push(list_nodes[i]);
        }
        // temp.shift();
        list_nodes = temp;
        console.log("SCAN", list_nodes);
        return;
    }
    if (how === "C-SCAN") {
        if (list_nodes.indexOf(99) < 0) list_nodes.push(99);
        if (list_nodes.indexOf(0) < 0) list_nodes.push(0);
        console.log(list_nodes);
        list_nodes.unshift(location);
        console.log("C-SCAN:before sort", list_nodes);
        // sort()
        list_nodes.sort((a, b)=>{return a - b});
        console.log("C-SCAN:sort", list_nodes);
        let temp_location = list_nodes.indexOf(location);
        let temp = [];
        for (let i = temp_location;i<list_nodes.length;i++){
            temp.push(list_nodes[i]);
        }
        for (let i = 0;i<temp_location;i++){
            temp.push(list_nodes[i]);
        }
        // temp.shift();
        list_nodes = temp;
        console.log("C-SCAN", list_nodes);
        return;
    }
    if (how === "LOOK") {
        list_nodes.unshift(location);
        console.log("SCAN:before sort", list_nodes);
        // sort()
        list_nodes.sort((a, b)=>{return a - b});
        console.log("SCAN:sort", list_nodes);
        let temp_location = list_nodes.indexOf(location);
        let temp = [];
        for (let i = temp_location;i<list_nodes.length;i++){
            temp.push(list_nodes[i]);
        }
        for (let i = temp_location-1;i>=0;i--){
            temp.push(list_nodes[i]);
        }
        // temp.shift();
        list_nodes = temp;
        console.log("SCAN", list_nodes);
        return;
    }
    if (how === "C-LOOK") {
        list_nodes.unshift(location);
        console.log("C-SCAN:before sort", list_nodes);
        // sort()
        list_nodes.sort((a, b)=>{return a - b});
        console.log("C-SCAN:sort", list_nodes);
        let temp_location = list_nodes.indexOf(location);
        let temp = [];
        for (let i = temp_location;i<list_nodes.length;i++){
            temp.push(list_nodes[i]);
        }
        for (let i = 0;i<temp_location;i++){
            temp.push(list_nodes[i]);
        }
        // temp.shift();
        list_nodes = temp;
        console.log("C-SCAN", list_nodes);
    }
};

// Layui config.
layui.use(["jquery", "form", "layer"], () => {
    const $ = layui.jquery;
    let form = layui.form;
    let layer = layui.layer;
    // 为按钮绑定事件
    $("#begin_stop_canvas_btn").on("click", () => {
        if (show_list.length === 0) {
            console.log("show_list 为空");
            return;
        }
        if (time_interval === null) {
            if (list_nodes.length > 0) {
                begin_interval();
            }
        }
        else {
            stop_interval();
        }
    });
    // 监听提交
    form.on('submit(formDemo)', function (data) {
        // clear the data what has been drawn.
        show_list = [];
        // log the input
        console.log(data);
        // get the data submitted
        let {location, how, seq} = data.field;
        let intLocation = 0;
        try {
            intLocation = parseInt(location.trim(), 10);
            if (intLocation < 0 || intLocation > 99) return false;
        } catch (e) {
            console.log("起始位置解析出错", location);
            return false;
        }
        initShowList(intLocation);
        pointer = new Triangle(
            new Point(intLocation, 0),
            new Point(intLocation - 1, -10),
            new Point(intLocation + 1, -10)
        );
        trackNumberText = new TextLabel({
            x: intLocation + 1,
            y: -2,
            text: "Pointer",
            font: "20px Arial"
        });
        if (seq.indexOf("，") > 0) {
            layer.msg("输入不应含有中文字符");
            return false;
        }
        console.log(location, how, seq);
        let howList = [];
        try {
            let howStrList = seq.trim().split(",");
            console.log("howStrList", howStrList);
            let success = true;
            for (let i = 0; i < howStrList.length; i++) {
                let tmp = parseInt(howStrList[i].trim(), 10);
                if (tmp >= 0 && tmp < 100) {
                    howList.push(tmp);
                }
                else {
                    success = false;
                    break;
                }
            }
            if (howStrList.length === 0 || seq === "" || seq === ",") {
                layer.msg("输入不能为空");
                return false;
            }
            else if (success === true) {
                list_nodes = howList;
            } else {
                layer.msg("输入错误");
            }
            console.log("list_nodes", list_nodes);
            // decide the list_node based on the concrete algorithm.
            generate_list_node(how, intLocation);
            // 开始执行动画
            if (show_list.length === 0) {
                console.log("show_list 为空");
                return;
            }
            if (time_interval === null) {
                if (list_nodes.length > 0) {
                    begin_interval();
                }
            }
            else {
                stop_interval();
            }
        } catch (e) {
            console.error("Error:", e);
            layer.alert("解析错误，请检查输入")
        }
        return false;
    });
});